<?php
fily_XMLConverter::registerNamespace('controlcontainer', fily_ControlContainer);
/**
 * Represents a basic html fily_Control.
 */
class fily_ControlContainer extends fily_Control {


    /**
     * array of all inner controls
     * @var fily_ControlList
     */
    public $controls;


    /**
     * array that contains all trigger objects
     * @var array
     */
    protected $updateTriggers = array();


    /**
     * path to file for the ajax request
     * @var string
     */
    protected $requestFile = '';



    /**
     *
     * @param string $tag the html tag
     */
    public function __construct($tag='') {
        parent::__construct($tag);
        $this->controls = new fily_ControlList();
        $this->controls->setParent($this);
    }


    //overwrite
    protected function generateHtml() {
        $html = '';
        if($this->controls->count()==0) {
            if(!$this->getEndTagRequired()) {
                $html .= '<' . $this->getTag() . $this->attributes->toString() . ' />';
            }
            else {
                $html .= '<' . $this->getTag() . $this->attributes->toString() . ' ></'. $this->getTag() .'>';
            }
        }
        else {
            $html .= '<' . $this->getTag() . $this->attributes->toString() . '>';
            $html .= $this->controls->toHtml();
            $html .= '</' . $this->getTag() . '>';
        }
        $this->prepared = false;
        return $html;
    }



    /**
     * prepares the control for the html output
     */
    public function prepare() {
        parent::prepare();


        if(count($this->updateTriggers)>0) {
            $loadingControlHtml = "null";
            if($this->getLoadingControl()!=null) {
                $loadingControlHtml = "'".$this->getLoadingControl()->toHtml(). "'";
            }

            $code = sprintf("var fily_init_temp_%s_AjaxContainer = firelynx.AjaxContainer('%s', '%s', %s);", $this->getId(), $this->getId(), $this->getRequestFile(), $loadingControlHtml);
            fily_ClientCodeManager::addCode($code);
            fily_ClientCodeManager::useId($this->getId());

            foreach ($this->updateTriggers as $updateTrigger) {
                $code = sprintf("fily_init_temp_%s_AjaxContainer.addTrigger('%s', '%s', %s);", $this->getId(), $updateTrigger['control']->getId(),  $updateTrigger['event'], $updateTrigger['executionTime']);
                fily_ClientCodeManager::addCode($code);
                fily_ClientCodeManager::useId($updateTrigger['control']->getId());
             }
            foreach ($this->ajaxEvents as $ajaxEvents) {
                $code = sprintf("firelynx.listenToEvent(fily_init_temp_%s_AjaxContainer,'%s', %s, %s); ", $this->getId(), $ajaxEvents['event'],$ajaxEvents['executionTime'],$ajaxEvents['function'] );
                fily_ClientCodeManager::addCode($code);
            }
        }
        // prepare inner controls
        $this->controls->prepare();
    }



    /**
     * Add a trigger for an ajax request
     * @param fily_Control $triggerControl the control that triggers the event
     * @param string $triggerEvent javascript event (onclick, onchange)
     * @param int $executionZone
     */
    public function addUpdateTrigger(fily_Control $triggerControl, $triggerEvent, $executionTime = 800) {
        $this->updateTriggers[] = array('control' => $triggerControl, 'event' => $triggerEvent,  'executionTime' => $executionTime);
    }


    protected $ajaxEvents = array();

    /**
     * calls a javascript function on a event
     * @param string $event
     * @param string $function
     * @param int $executionZone
     */
    public function onAjaxEvent($event, $function, $executionTime = 500) {
        $this->ajaxEvents[] = array(
                'event' => $event,
                'function' => $function,
                'executionTime' => $executionTime,
        );
    }


    /**
     * get the path for the ajax request file
     * @return string
     */
    public function getRequestFile() {
        return $this->requestFile;
    }

    /**
     * set the path to the ajax request file
     * @param string $value
     */
    public function setRequestFile($value) {
        $this->requestFile= $value;
    }

    /**
     * control that is showed while loading
     * @var fily_Control
     */
    protected $loadingControl;


    /**
     * get the loading control
     * @return <type>
     */
    public function getLoadingControl() {
        return $this->loadingControl;
    }

    /**
     * set the control which is showing while loading
     * @param fily_Control $control
     */
    public function setLoadingControl(fily_ControlToHtml $control) {
        $this->loadingControl = $control;
    }

    /**
     * finds a control with the specific id
     * @param string $id
     * @return fily_ControlToHtml
     */
    public function getControlById($id) {
        return $this->controls->getControlById($id);
    }

     /**
     * finds a control with the specific system id
     * @param string $sid
     * @return fily_ControlToHtml
     */
    public function getControlBySid($sid) {
        return $this->controls->getControlBySid($sid);
    }
    public function XMLAddControl(fily_ControlToHtml $control) {
        $this->controls->add($control);
    }

    public function XMLAttributes(array $attributes, $innerValue) {
        $innerValue = trim($innerValue);
        if(!empty($innerValue)) {
            $this->controls->add(new fily_Text($innerValue));
        }
        foreach($attributes as $key => $value) {
            switch ($key) {
                case 'requestfile':
                    $this->setRequestFile($value);
                    unset($attributes[$key]);
                    break;
            }
        }
        parent::XMLAttributes($attributes, $innerValue);
    }


    public function XMLCallFunction($name, array $parameters,$innerValue,fily_ControlToHtml $innerControl = null) {
        switch ($name) {
            case 'addupdatetrigger':
                // add to array for late binding
                $this->lateBindingObjects[$name][] = $parameters;
                break;
            case 'setloadingcontrol':
                $this->setLoadingControl($innerControl);
                break;
                         case 'onajaxevent':
                    if(isset($parameters['executiontime']) ){
                        $this->onAjaxEvent($parameters['event'], $parameters['function'], $parameters['executiontime']);
                    }
                    else{
                        $this->onAjaxEvent($parameters['event'], $parameters['function']);
                    }

                    unset($this->lateBindingObjects[$key]);
                    break;
            default :
                parent::XMLCallFunction($name, $parameters, $innerValue, $innerControl);
                break;
        }
    }

    public function XMLLateBinding(fily_ControlToHtml $baseControl) {
        foreach($this->lateBindingObjects as $key => $value) {
            switch ($key) {
                case 'addupdatetrigger':
                    foreach ($this->lateBindingObjects[$key] as $parameters) {
                         $control = fily_XMLConverter::findControl($parameters['control'], $this, $baseControl);

                        if($control!=null) {
                            if(!isset($parameters['executiontime'])) {
                                $this->addUpdateTrigger($control, $parameters['event']);
                            }
                            else {
                                $this->addUpdateTrigger($control, $parameters['event'],$parameters['executiontime']);
                            }
                        }

                    }
                    unset($this->lateBindingObjects[$key]);
                    break;
                   
            }
        }
        parent::XMLLateBinding($baseControl);
    }

    // overwrite completely
    public function find($expression) {
        $control = null;
        if(!fily_ExpressionHelper::isExpression($expression)) {
            //expression is an id
            $control = $this->getControlById($expression);
        }
        else {
            $expressionParts = fily_ExpressionHelper::getParts($expression) ;
            // first expression part is always empty
            if(count($expressionParts)>1) {
                switch ($expressionParts[1]) {
                    case 'next':
                        $control =  fily_ExpressionHelper::next($expressionParts, $expression, $this);
                        break;
                    case 'previous':
                        $control = fily_ExpressionHelper::previous($expressionParts, $expression, $this);
                        break;
                    case 'after':
                        $control = fily_ExpressionHelper::after($expressionParts, $expression, $this->controls);
                        break;
                    case  'before':
                        $control = fily_ExpressionHelper::before($expressionParts, $expression, $this->controls);
                        break;
                    case 'parent':
                        $control = fily_ExpressionHelper::parent($expressionParts, $expression, $this);
                        break;
                    case 'first':
                        $control = fily_ExpressionHelper::first($expressionParts, $expression, $this->controls);
                        break;
                    case 'last':
                        $control = fily_ExpressionHelper::last($expressionParts, $expression,  $this->controls);
                        break;
                    case 'child':
                        $control = fily_ExpressionHelper::child($expressionParts, $expression, $this->controls);
                        break;
                    case 'root':
                        $control = fily_ExpressionHelper::root($expressionParts, $expression, $this);
                        break;
                }
            }
            // found a control and have another expressions
            if($control!=null && !empty($expression)) {
                $control = $control->find($expression);
            }
        }
        return $control;
    }

}
?>
